/******************************************************************************
 * * call_log_proc.c - process user key event of call log module
 *
 * *(C) Copyright 2019 Asr International Ltd.
 * * All Rights Reserved
 * ******************************************************************************/

#include "call_log_global.h"

/**
 * process button Call_Log_Menu -> Mssed calls
 */
VOID Call_Log_Proc_Btn_Missed_Calls(lv_obj_t *Btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED != e) {
        return;
    }

    if (0 == g_Call_Log_Mng.MissedCalls)
    {
        Display_Call_Log_No_Numbers();
    }
    else
    {
        g_Call_Log_Mng.CurrCallLog = NULL;
        Display_Call_Log_Call_List(CALL_LOG_TYPE_MISSED, TRUE, ACT_ID_ANY);
    }
}

/**
 * process button Call_Log_Menu -> Received calls
 */
VOID Call_Log_Proc_Btn_Received_Calls(lv_obj_t *Btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED != e) {
        return;
    }

    if (0 == g_Call_Log_Mng.ReceivedCalls)
    {
        Display_Call_Log_No_Numbers();
    }
    else
    {
        g_Call_Log_Mng.CurrCallLog = NULL;
        Display_Call_Log_Call_List(CALL_LOG_TYPE_RECEIVED, TRUE, ACT_ID_ANY);
    }
}

/**
 * process button Call_Log_Menu -> Dialled calls
 */
VOID Call_Log_Proc_Btn_Dialled_Calls(lv_obj_t *Btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED != e) {
        return;
    }

    if (0 == g_Call_Log_Mng.DialledCalls)
    {
        Display_Call_Log_No_Numbers();
    }
    else
    {
        g_Call_Log_Mng.CurrCallLog = NULL;
        Display_Call_Log_Call_List(CALL_LOG_TYPE_DIALLED, TRUE, ACT_ID_ANY);
    }
}

/**
 * process button Call_Log_Menu -> Delete recent call list
 */
VOID Call_Log_Proc_Btn_Del_Recent_Calls(lv_obj_t *Btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED != e) {
        return;
    }

    Display_Call_Log_Delete_List();
}

/**
 * process key event of Call_Log_Menu
 */
UINT8 Call_Log_Proc_Key_Menu(lv_obj_t *obj, UI_KEY_STATUS key_sta, UI_KEY_VALUE key_val)
{
    UINT8                      Ret   = 0; /* 0: call default signal func, 1: otherwise */
    UI_Normal_List_Only_Desc_t *Desc = (UI_Normal_List_Only_Desc_t *)g_Call_Log_Mng.CurrDesc;

    if (KEY_RELEASED == key_sta)
    {
        switch (key_val)
        {
        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            Ret = 1;
            break;

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            Ret = 1;
            break;

        case KEY_OK:
            break;

        case KEY_UP:
        case KEY_LEFT:
            if (Desc->List.Index > 0)
            {
                Desc->List.Index--;
            }
            else
            {
                Desc->List.Index = Desc->List.ListButtonCnt - 1;
            }
            break;

        case KEY_DOWN:
        case KEY_RIGHT:
            if (Desc->List.Index + 1 < Desc->List.ListButtonCnt)
            {
                Desc->List.Index++;
            }
            else
            {
                Desc->List.Index = 0;
            }
            break;

        default:
            break;
        } /* switch */
    }

    return(Ret);
} /* Call_Log_Proc_Key_Menu */

/**
 * select next list button
 * param (in) List: lv_obj_t *
 * param (in) Loop: BOOL
 * return VOID
 */
VOID Call_Log_Proc_List_Select_Next(lv_obj_t *List, BOOL Loop)
{
    lv_list_ext_t *ext = lv_obj_get_ext_attr(List);

    /*If there is a valid selected button the make the previous selected*/
    if (ext->act_sel_btn)
    {
        lv_obj_t *btn_prev = lv_list_get_next_btn(List, ext->act_sel_btn);
        if (btn_prev)
        {
            lv_list_focus_btn(List, btn_prev);
        }

        if (Loop)    /*for Loop selection*/
        {
            if (NULL == btn_prev)
            {
                lv_obj_t *btn = lv_list_get_next_btn(List, NULL);
                if (btn)
                {
                    lv_list_focus_btn(List, btn);
                }
            }
        }
    }
    /*If there is no selected button the make the first selected*/
    else
    {
        lv_obj_t *btn = lv_list_get_next_btn(List, NULL);
        if (btn)
        {
            lv_list_focus_btn(List, btn);        /*If there are no buttons on the list then there is no first button*/
        }
    }
}

/**
 * select previous list button
 * param (in) List: lv_obj_t *
 * param (in) Loop: BOOL
 * return VOID
 */
VOID Call_Log_Proc_List_Select_Prev(lv_obj_t *List, BOOL Loop)
{
    lv_list_ext_t *ext = lv_obj_get_ext_attr(List);

    /*If there is a valid selected button the make the next selected*/
    if (ext->act_sel_btn != NULL)
    {
        lv_obj_t *btn_next = lv_list_get_prev_btn(List, ext->act_sel_btn);
        if (btn_next)
        {
            lv_list_focus_btn(List, btn_next);
        }

        if (Loop)    /*for Loop selection*/
        {
            if (NULL == btn_next)
            {
                lv_obj_t *btn = lv_list_get_prev_btn(List, NULL);
                if (btn)
                {
                    lv_list_focus_btn(List, btn);
                }
            }
        }
    }
    /*If there is no selected button the make the first selected*/
    else
    {
        lv_obj_t *btn = lv_list_get_next_btn(List, NULL);
        if (btn)
        {
            lv_list_focus_btn(List, btn);
        }
    }
}

/**
 * process key event of Call_Log_Call_List
 */
UINT8 Call_Log_Proc_Key_Call_List(lv_obj_t *obj, UI_KEY_STATUS key_sta, UI_KEY_VALUE key_val)
{
    UI_Normal_Container_List_Desc_t *pDesc       = NULL;
    Call_Log_Node_t                 *CallLogNext = NULL;
    Call_Log_Node_t                 *CallLogPrev = NULL;
    INT8                            *Number      = NULL;
    UINT8                           Len          = 0;
    UINT8                           Ret          = 1; /* 0: call default signal func, 1: otherwise */

    pDesc = (UI_Normal_Container_List_Desc_t *)g_Call_Log_Mng.CurrDesc;

    if (KEY_RELEASED == key_sta)
    {
        switch (key_val)
        {
        case KEY_SOFTLEFT:
        case KEY_OK:
            Display_Call_Log_Opt();
            break;

        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            break;

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            break;

        case KEY_DIAL:
            Len    = NV_CONTACTS_MAX_NUMBER_LEN * sizeof(INT8);
            Number = (INT8 *)Hal_Mem_Alloc(Len);
            Hal_Mem_Copy(Number, g_Call_Log_Mng.CurrCallLog->Data.Number, Len);

            Call_Framework_Voice_Call_Req(Number);
            break;

        case KEY_UP:
        case KEY_LEFT:
            /* get previous call log of current type*/
            CallLogPrev = _lv_ll_get_prev(&g_Call_Log_Mng.CallLogList, g_Call_Log_Mng.CurrCallLog);
            while (CallLogPrev)
            {
                if (g_Call_Log_Mng.CurrType == CallLogPrev->Data.Type)
                {
                    break;
                }
                CallLogPrev = _lv_ll_get_prev(&g_Call_Log_Mng.CallLogList, CallLogPrev);
            }

            if (NULL != CallLogPrev)
            {
                if (pDesc->ContList.Index > 0)
                {
                    pDesc->ContList.Index--;
                }

                Call_Log_Proc_List_Select_Prev(pDesc->List, FALSE);
            }
            else    /* for Loop selection */
            {
                pDesc->ContList.Index = pDesc->ContList.ListContainerCnt - 1;

                CallLogPrev = _lv_ll_get_tail(&g_Call_Log_Mng.CallLogList);
                while (CallLogPrev)
                {
                    if (g_Call_Log_Mng.CurrType == CallLogPrev->Data.Type)
                    {
                        break;
                    }
                    CallLogPrev = _lv_ll_get_prev(&g_Call_Log_Mng.CallLogList, CallLogPrev);
                }

                Call_Log_Proc_List_Select_Prev(pDesc->List, TRUE);
            }

            /* set current call log */
            g_Call_Log_Mng.CurrCallLog = CallLogPrev;

            /* set label txt */
            Call_Log_Call_List_Set_Label(g_Call_Log_Mng.CurrDesc);
            break;

        case KEY_DOWN:
        case KEY_RIGHT:
            /* get next call log of current type*/
            CallLogNext = _lv_ll_get_next(&g_Call_Log_Mng.CallLogList, g_Call_Log_Mng.CurrCallLog);
            while (CallLogNext)
            {
                if (g_Call_Log_Mng.CurrType == CallLogNext->Data.Type)
                {
                    break;
                }
                CallLogNext = _lv_ll_get_next(&g_Call_Log_Mng.CallLogList, CallLogNext);
            }

            if (NULL != CallLogNext)
            {
                if ((pDesc->ContList.Index + 1) < pDesc->ContList.ListContainerCnt)
                {
                    pDesc->ContList.Index++;
                }

                Call_Log_Proc_List_Select_Next(pDesc->List, FALSE);
            }
            else    /* for Loop selection */
            {
                pDesc->ContList.Index = 0;

                CallLogNext = _lv_ll_get_head(&g_Call_Log_Mng.CallLogList);
                while (CallLogNext)
                {
                    if (g_Call_Log_Mng.CurrType == CallLogNext->Data.Type)
                    {
                        break;
                    }
                    CallLogNext = _lv_ll_get_next(&g_Call_Log_Mng.CallLogList, CallLogNext);
                }

                Call_Log_Proc_List_Select_Next(pDesc->List, TRUE);
            }

            /* set current call log */
            g_Call_Log_Mng.CurrCallLog = CallLogNext;

            /* set label txt */
            Call_Log_Call_List_Set_Label(g_Call_Log_Mng.CurrDesc);
            break;

        default:
            break;
        } /* switch */
    }

    return(Ret);
} /* Call_Log_Proc_Key_Call_List */

/**
 * process button Call_Log_Opt -> Call
 */
VOID Call_Log_Proc_Btn_Call(lv_obj_t *Btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED != e) {
        return;
    }

    UINT8 Len     = NV_CONTACTS_MAX_NUMBER_LEN * sizeof(INT8);
    INT8  *Number = (INT8 *)Hal_Mem_Alloc(Len);

    Hal_Mem_Copy(Number, g_Call_Log_Mng.CurrCallLog->Data.Number, Len);

    Call_Framework_Voice_Call_Req(Number);
}

/**
 * process button Call_Log_Opt -> Call history
 */
VOID Call_Log_Proc_Btn_Call_History(lv_obj_t *Btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED != e) {
        return;
    }

    Display_Call_Log_History_List();
}

/**
 * process button Call_Log_Opt -> Send sms
 */
VOID Call_Log_Proc_Btn_Send_Sms(lv_obj_t *Btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED != e) {
        return;
    }

    UINT8 Len     = NV_CONTACTS_MAX_NUMBER_LEN * sizeof(INT8);
    INT8  *Number = (INT8 *)Hal_Mem_Alloc(Len);

    Hal_Mem_Copy(Number, g_Call_Log_Mng.CurrCallLog->Data.Number, Len);

    Call_Send_Sms_Req(Number, NULL);
}

/**
 * process button Call_Log_Opt -> Send number
 */
VOID Call_Log_Proc_Btn_Send_Number(lv_obj_t *Btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED != e) {
        return;
    }

    UINT8 Len     = NV_CONTACTS_MAX_NUMBER_LEN * sizeof(INT8);
    INT8  *Number = (INT8 *)Hal_Mem_Alloc(Len);

    Hal_Mem_Copy(Number, g_Call_Log_Mng.CurrCallLog->Data.Number, Len);

    Call_Send_Sms_Req(NULL, Number);
}

/**
 * process button Call_Log_Opt -> Save number
 */
VOID Call_Log_Proc_Btn_Save_Number(lv_obj_t *Btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED != e) {
        return;
    }

    UINT8 Len     = NV_CONTACTS_MAX_NUMBER_LEN * sizeof(INT8);
    INT8  *Number = (INT8 *)Hal_Mem_Alloc(Len);

    Hal_Mem_Copy(Number, g_Call_Log_Mng.CurrCallLog->Data.Number, Len);

    Contacts_Save_Contact_Req(ACT_ID_CALL_LOG_OPT, Number);
}

/**
 * process button Call_Log_Opt -> Delete number
 */
VOID Call_Log_Proc_Btn_Del_Number(lv_obj_t *Btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED != e) {
        return;
    }

    Display_Call_Log_Delete_Number_Inquire();
}

/**
 * process button Call_Log_Opt -> Add to scrn list
 */
VOID Call_Log_Proc_Btn_Add_To_Scrn_List(lv_obj_t *Btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED != e) {
        return;
    }

    UINT8 Len     = NV_CONTACTS_MAX_NUMBER_LEN * sizeof(INT8);
    INT8  *Number = (INT8 *)Hal_Mem_Alloc(Len);

    Hal_Mem_Copy(Number, g_Call_Log_Mng.CurrCallLog->Data.Number, Len);

    Contacts_Add_Num_To_Scrn_List_Req(ACT_ID_CALL_LOG_OPT, Number);
}

/**
 * process key event of Call_Log_Opt
 */
UINT8 Call_Log_Proc_Key_Opt(lv_obj_t *obj, UI_KEY_STATUS key_sta, UI_KEY_VALUE key_val)
{
    UINT8                      Ret   = 0; /* 0: call default signal func, 1: otherwise */
    UI_Normal_List_Only_Desc_t *Desc = (UI_Normal_List_Only_Desc_t *)g_Call_Log_Mng.CurrDesc;

    if (KEY_RELEASED == key_sta)
    {
        switch (key_val)
        {
        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            Ret = 1;
            break;

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            Ret = 1;
            break;

        case KEY_OK:
            break;

        case KEY_UP:
        case KEY_LEFT:
            if (Desc->List.Index > 0)
            {
                Desc->List.Index--;
            }
            else
            {
                Desc->List.Index = Desc->List.ListButtonCnt - 1;
            }
            break;

        case KEY_DOWN:
        case KEY_RIGHT:
            if (Desc->List.Index + 1 < Desc->List.ListButtonCnt)
            {
                Desc->List.Index++;
            }
            else
            {
                Desc->List.Index = 0;
            }
            break;

        default:
            break;
        } /* switch */
    }

    return(Ret);
} /* Call_Log_Proc_Key_Opt */

/**
 * process key event of Call_Log_History_List
 */
UINT8 Call_Log_Proc_Key_History_List(lv_obj_t *obj, UI_KEY_STATUS key_sta, UI_KEY_VALUE key_val)
{
    UI_Normal_Container_List_Desc_t *pDesc       = NULL;
    Call_Log_Node_t                 *CallLogNext = NULL;
    Call_Log_Node_t                 *CallLogPrev = NULL;
    UINT8                           Ret          = 1; /* 0: call default signal func, 1: otherwise */

    pDesc = (UI_Normal_Container_List_Desc_t *)g_Call_Log_Mng.CurrDesc;

    if (KEY_RELEASED == key_sta)
    {
        switch (key_val)
        {
        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            break;

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            break;

        case KEY_UP:
        case KEY_LEFT:
            /* get previous call log of current type*/
            CallLogPrev = _lv_ll_get_prev(&g_Call_Log_Mng.CallLogList, g_Call_Log_Mng.HisCallLog);
            while (CallLogPrev)
            {
                if (  (g_Call_Log_Mng.CurrType == CallLogPrev->Data.Type)
                   && (0 == strcmp(g_Call_Log_Mng.CurrCallLog->Data.Number, CallLogPrev->Data.Number)))
                {
                    break;
                }
                CallLogPrev = _lv_ll_get_prev(&g_Call_Log_Mng.CallLogList, CallLogPrev);
            }

            if (NULL != CallLogPrev)
            {
                if (pDesc->ContList.Index > 0)
                {
                    pDesc->ContList.Index--;
                }

                Call_Log_Proc_List_Select_Prev(pDesc->List, FALSE);
            }
            else    /* for Loop selection */
            {
                pDesc->ContList.Index = pDesc->ContList.ListContainerCnt - 1;

                CallLogPrev = _lv_ll_get_tail(&g_Call_Log_Mng.CallLogList);
                while (CallLogPrev)
                {
                    if (  (g_Call_Log_Mng.CurrType == CallLogPrev->Data.Type)
                       && (0 == strcmp(g_Call_Log_Mng.CurrCallLog->Data.Number, CallLogPrev->Data.Number)))
                    {
                        break;
                    }
                    CallLogPrev = _lv_ll_get_prev(&g_Call_Log_Mng.CallLogList, CallLogPrev);
                }

                Call_Log_Proc_List_Select_Prev(pDesc->List, TRUE);
            }

            /* set current call log */
            g_Call_Log_Mng.HisCallLog = CallLogPrev;

            /* set label txt */
            Call_Log_History_List_Set_Label(g_Call_Log_Mng.CurrDesc);
            break;

        case KEY_DOWN:
        case KEY_RIGHT:
            /* get next call log of current type*/
            CallLogNext = _lv_ll_get_next(&g_Call_Log_Mng.CallLogList, g_Call_Log_Mng.HisCallLog);
            while (CallLogNext)
            {
                if (  (g_Call_Log_Mng.CurrType == CallLogNext->Data.Type)
                   && (0 == strcmp(g_Call_Log_Mng.CurrCallLog->Data.Number, CallLogNext->Data.Number)))
                {
                    break;
                }
                CallLogNext = _lv_ll_get_next(&g_Call_Log_Mng.CallLogList, CallLogNext);
            }

            if (NULL != CallLogNext)
            {
                if ((pDesc->ContList.Index + 1) < pDesc->ContList.ListContainerCnt)
                {
                    pDesc->ContList.Index++;
                }

                Call_Log_Proc_List_Select_Next(pDesc->List, FALSE);
            }
            else    /* for Loop selection */
            {
                pDesc->ContList.Index = 0;

                CallLogNext = _lv_ll_get_head(&g_Call_Log_Mng.CallLogList);
                while (CallLogNext)
                {
                    if (  (g_Call_Log_Mng.CurrType == CallLogNext->Data.Type)
                       && (0 == strcmp(g_Call_Log_Mng.CurrCallLog->Data.Number, CallLogNext->Data.Number)))
                    {
                        break;
                    }
                    CallLogNext = _lv_ll_get_next(&g_Call_Log_Mng.CallLogList, CallLogNext);
                }

                Call_Log_Proc_List_Select_Next(pDesc->List, TRUE);
            }

            /* set current call log */
            g_Call_Log_Mng.HisCallLog = CallLogNext;

            /* set label txt */
            Call_Log_History_List_Set_Label(g_Call_Log_Mng.CurrDesc);
            break;

        default:
            break;
        } /* switch */
    }

    return(Ret);
} /* Call_Log_Proc_Key_History_List */

/**
 * process key event of Call_Log_Delete_Number_Inquire
 */
UINT8 Call_Log_Proc_Key_Delete_Number_Inquire(lv_obj_t *obj, UI_KEY_STATUS key_sta, UI_KEY_VALUE key_val)
{
    Call_Log_Node_t    *CallLog;
    NV_Call_Log_Data_t NvData;
    UINT32             Offset = 0;
    UINT8              Ret    = 0; /* 0: call default signal func, 1: otherwise */

    if (KEY_RELEASED == key_sta)
    {
        switch (key_val)
        {
        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            Ret = 1;
            break;

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            Ret = 1;
            break;

        case KEY_OK:
            if (g_Call_Log_Mng.CurrCallLog)
            {
                /* set current call log to a new one */
                CallLog = _lv_ll_get_next(&g_Call_Log_Mng.CallLogList, g_Call_Log_Mng.CurrCallLog);
                while (CallLog)
                {
                    if (g_Call_Log_Mng.CurrType == CallLog->Data.Type)
                    {
                        break;
                    }
                    CallLog = _lv_ll_get_next(&g_Call_Log_Mng.CallLogList, CallLog);
                }

                if (NULL == CallLog)
                {
                    CallLog = _lv_ll_get_prev(&g_Call_Log_Mng.CallLogList, g_Call_Log_Mng.CurrCallLog);
                    while (CallLog)
                    {
                        if (g_Call_Log_Mng.CurrType == CallLog->Data.Type)
                        {
                            break;
                        }
                        CallLog = _lv_ll_get_prev(&g_Call_Log_Mng.CallLogList, CallLog);
                    }
                }

                /* write to NVM */
                Hal_Mem_Set(&NvData, 0, sizeof(NV_Call_Log_Data_t));
                Offset = g_Call_Log_Mng.CurrCallLog->BlockId * sizeof(NV_Call_Log_Data_t);
                UI_NV_Write_Req(NV_SECTION_UI_CALL_LOG, Offset, sizeof(NV_Call_Log_Data_t), (UINT8 *)&NvData);

                /* free block */
                Block_Free(g_Call_Log_Mng.CurrCallLog->BlockId);

                /* decrease call log count */
                Call_Log_Update_Cnt(g_Call_Log_Mng.CurrType, -1);

                /* delete call log from list */
                _lv_ll_remove(&g_Call_Log_Mng.CallLogList, g_Call_Log_Mng.CurrCallLog);
                lv_mem_free(g_Call_Log_Mng.CurrCallLog);

                g_Call_Log_Mng.CurrCallLog = CallLog;
            }

            /* display next UI */
            Display_Call_Log_Delete_Number_Done();
            Ret = 1;
            break;

        default:
            break;
        } /* switch */
    }

    return(Ret);
} /* Call_Log_Proc_Key_Delete_Number_Inquire */

/**
 * delete call logs of specified type from list
 * param Node: Call_Log_Node_t *
 * return VOID
 */
static VOID Call_Log_Proc_Del_Type(CALL_LOG_TYPE Type)
{
    Call_Log_Node_t *CallLogNext = NULL;
    Call_Log_Node_t *CallLogTmp  = NULL;

    if (CALL_LOG_TYPE_ALL == Type)
    {
        _lv_ll_clear(&g_Call_Log_Mng.CallLogList);
    }
    else
    {
        CallLogNext = _lv_ll_get_head(&g_Call_Log_Mng.CallLogList);

        while (CallLogNext)
        {
            CallLogTmp = _lv_ll_get_next(&g_Call_Log_Mng.CallLogList, CallLogNext);

            if (Type == CallLogNext->Data.Type)
            {
                _lv_ll_remove(&g_Call_Log_Mng.CallLogList, CallLogNext);
                lv_mem_free(CallLogNext);
            }

            CallLogNext = CallLogTmp;
        }
    }
}

/**
 * delete recent call log list
 * param Node: Call_Log_Node_t *
 * return VOID
 */
static VOID Call_Log_Proc_Del_List(CALL_LOG_TYPE Type)
{
    NV_UI_Call_Log_t NvData;
    Call_Log_Node_t  *CallLogNext = NULL;
    BOOL             NoNumber     = FALSE;
    UINT16           Index        = 0;

    Hal_Mem_Set(&NvData, 0, sizeof(NV_UI_Call_Log_t));

    /* reset call log count*/
    switch (Type)
    {
    case CALL_LOG_TYPE_MISSED:
        if (0 == g_Call_Log_Mng.MissedCalls)
        {
            NoNumber = TRUE;
        }
        g_Call_Log_Mng.MissedCalls       = 0;
        g_Call_Log_Mng.UnreadMissedCalls = 0;
        break;

    case CALL_LOG_TYPE_RECEIVED:
        if (0 == g_Call_Log_Mng.ReceivedCalls)
        {
            NoNumber = TRUE;
        }
        g_Call_Log_Mng.ReceivedCalls = 0;
        break;

    case CALL_LOG_TYPE_DIALLED:
        if (0 == g_Call_Log_Mng.DialledCalls)
        {
            NoNumber = TRUE;
        }
        g_Call_Log_Mng.DialledCalls = 0;
        break;

    case CALL_LOG_TYPE_ALL:
        if (0 == g_Call_Log_Mng.MissedCalls + g_Call_Log_Mng.ReceivedCalls + g_Call_Log_Mng.DialledCalls)
        {
            NoNumber = TRUE;
        }
        g_Call_Log_Mng.MissedCalls       = 0;
        g_Call_Log_Mng.UnreadMissedCalls = 0;
        g_Call_Log_Mng.ReceivedCalls     = 0;
        g_Call_Log_Mng.DialledCalls      = 0;
        break;

    default:
        break;
    }

    if (NoNumber)
    {
        return;
    }

    /* delete call log from list */
    Call_Log_Proc_Del_Type(Type);

    /* reset block bitmap */
    Hal_Mem_Set(g_Call_Log_Mng.BlockBitmap, 0, NV_CALL_LOG_MAX_NUM / 8 + 1);

    CallLogNext = _lv_ll_get_head(&g_Call_Log_Mng.CallLogList);
    while (CallLogNext)
    {
        /* set block ID */
        CallLogNext->BlockId = Index;
        Block_Set_State(Index, 1);

        /* memcpy call log to NvData */
        Hal_Mem_Copy(&NvData.CallLog[Index], &CallLogNext->Data, sizeof(NV_Call_Log_Data_t));

        Index++;
        CallLogNext = _lv_ll_get_next(&g_Call_Log_Mng.CallLogList, CallLogNext);
    }

    NvData.UnreadMissedCalls = g_Call_Log_Mng.UnreadMissedCalls;

    /* write to NVM */
    UI_NV_Write_Req(NV_SECTION_UI_CALL_LOG, 0, sizeof(NV_UI_Call_Log_t), (UINT8 *)&NvData);
} /* Call_Log_Proc_Del_List */

/**
 * process button Call_Log_Delete_List -> Delete all
 */
VOID Call_Log_Proc_Btn_Del_All(lv_obj_t *Btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED != e) {
        return;
    }

    /* delete all call list */
    Call_Log_Proc_Del_List(CALL_LOG_TYPE_ALL);

    /* indicate framework the missed calls have been read */
    Framework_CallLog_Missed_Call_Read_Ind();

    /* display next UI */
    Display_Call_Log_Delete_List_Done();
}

/**
 * process button Call_Log_Delete_List -> Delete missed calls
 */
VOID Call_Log_Proc_Btn_Del_Missed(lv_obj_t *Btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED != e) {
        return;
    }

    /* delete all call list */
    Call_Log_Proc_Del_List(CALL_LOG_TYPE_MISSED);

    /* indicate framework the missed calls have been read */
    Framework_CallLog_Missed_Call_Read_Ind();

    /* display next UI */
    Display_Call_Log_Delete_List_Done();
}

/**
 * process button Call_Log_Delete_List -> Delete received calls
 */
VOID Call_Log_Proc_Btn_Del_Received(lv_obj_t *Btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED != e) {
        return;
    }

    /* delete all call list */
    Call_Log_Proc_Del_List(CALL_LOG_TYPE_RECEIVED);

    /* display next UI */
    Display_Call_Log_Delete_List_Done();
}

/**
 * process button Call_Log_Delete_List -> Delete dialled calls
 */
VOID Call_Log_Proc_Btn_Del_Dialled(lv_obj_t *Btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED != e) {
        return;
    }

    /* delete all Call_Log_Proc_Common_Del_List list */
    Call_Log_Proc_Del_List(CALL_LOG_TYPE_DIALLED);

    /* display next UI */
    Display_Call_Log_Delete_List_Done();
}

/**
 * process key event of Call_Log_Delete_List
 */
UINT8 Call_Log_Proc_Key_Delete_List(lv_obj_t *obj, UI_KEY_STATUS key_sta, UI_KEY_VALUE key_val)
{
    UINT8                      Ret   = 0; /* 0: call default signal func, 1: otherwise */
    UI_Normal_List_Only_Desc_t *Desc = (UI_Normal_List_Only_Desc_t *)g_Call_Log_Mng.CurrDesc;

    if (KEY_RELEASED == key_sta)
    {
        switch (key_val)
        {
        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            Ret = 1;
            break;

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            Ret = 1;
            break;

        case KEY_OK:
            break;

        case KEY_UP:
        case KEY_LEFT:
            if (Desc->List.Index > 0)
            {
                Desc->List.Index--;
            }
            else
            {
                Desc->List.Index = Desc->List.ListButtonCnt - 1;
            }
            break;

        case KEY_DOWN:
        case KEY_RIGHT:
            if (Desc->List.Index + 1 < Desc->List.ListButtonCnt)
            {
                Desc->List.Index++;
            }
            else
            {
                Desc->List.Index = 0;
            }
            break;

        default:
            break;
        } /* switch */
    }

    return(Ret);
} /* Call_Log_Proc_Key_Delete_List */

/**
 * process key event of Call_Log_No_Dialled_Numbers
 */
UINT8 Call_Log_Proc_Key_No_Dialled_Numbers(lv_obj_t *obj, UI_KEY_STATUS key_sta, UI_KEY_VALUE key_val)
{
    UINT8 Ret = 1;                 /* 0: call default signal func, 1: otherwise */

    if (KEY_RELEASED == key_sta)
    {
        switch (key_val)
        {
        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            break;

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            break;

        default:
            break;
        }
    }

    return(Ret);
}

/**
 * process key event of status
 */
UINT8 Call_Log_Proc_Key_Status(lv_obj_t *obj, UI_KEY_STATUS key_sta, UI_KEY_VALUE key_val)
{
    UINT8 Ret = 1;                 /* 0: call default signal func, 1: otherwise */

    if (KEY_RELEASED == key_sta)
    {
        switch (key_val)
        {
        case KEY_SOFTRIGHT:
            Hal_Timer_Stop(g_Call_Log_Mng.DisplayTimer);
            Call_Log_Proc_Status_Timeout((VOID*)&g_Call_Log_Mng.ActStatus);
            break;

        case KEY_END:
            Hal_Timer_Stop(g_Call_Log_Mng.DisplayTimer);
            Nav_Home(ACT_ID_ANY);
            break;

        default:
            break;
        }
    }

    return(Ret);
}

/**
 * process status timeout
 * param (in) Para:  activity ID of status
 * return VOID
 */
VOID Call_Log_Proc_Status_Timeout(VOID* Para)
{
    ACTIVITY_ID ActId = *(ACTIVITY_ID *)Para;
    printf("%s: ActId=%d\n", __FUNCTION__, ActId);

    switch (ActId)
    {
    case ACT_ID_CALL_LOG_NO_NUMBERS:
        Nav_Back(ActId);
        break;

    case ACT_ID_CALL_LOG_DELETE_NUMBER_DONE:
        if (Call_Log_Get_Cnt(g_Call_Log_Mng.CurrType) > 0)
        {
            Display_Call_Log_Call_List(g_Call_Log_Mng.CurrType, FALSE, ActId);
        }
        else
        {
            Nav_Forward(ActId, ACT_ID_CALL_LOG_MENU, NULL, NULL);
        }
        break;

    case ACT_ID_CALL_LOG_DELETE_LIST_DONE:
        Nav_Forward(ActId, ACT_ID_CALL_LOG_MENU, NULL, NULL);
        break;

    default:
        break;
    }
}
